/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.controller.admin;

import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.vos.EnvVo;
import cn.easyplatform.web.WebApps;
import cn.easyplatform.web.contexts.Contexts;
import cn.easyplatform.web.dialog.MessageBox;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zkoss.image.AImage;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Page;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.UploadEvent;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.Button;
import org.zkoss.zul.Image;
import org.zkoss.zul.Window;
import org.zkoss.zul.*;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Properties;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * @Author: <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @Description:
 * @Since: 2.0.0 <br/>
 * @Date: Created in 2019/11/26 10:35
 * @Modified By:
 */
public class TemplateDialog extends Window implements EventListener {

    private final static Logger logger = LoggerFactory.getLogger(TemplateDialog.class);

    private final static int IMG_WIDTH = 600;

    private final static int IMG_HEIGHT = 400;

    private Tabpanel privatePanel;

    private Tabpanel commonPanel;

    private PropertySetCallback<String> cb;

    private String type;

    private String name;

    private Grid container;

    private Grid commonContainer;

    /**
     * @param cb         回调
     * @param deviceType 客户端类型 ajax|mil，分别对应PC和移动端
     * @param type       登陆页面或是主页面
     * @param name       生成的目录名称
     */
    public TemplateDialog(PropertySetCallback<String> cb, String deviceType, String type, String name) {
        this.cb = cb;
        this.type = deviceType + "-" + type;
        this.name = name;
        setHeight("75%");
        setWidth("75%");
        Caption caption = new Caption();
        caption.setLabel(Labels.getLabel("admin.template.select") + ":" + Labels.getLabel("admin.template." + deviceType.toLowerCase() + "." + type));
        caption.setParent(this);

        Tabbox textbox = new Tabbox();
        textbox.setHflex("1");
        textbox.setVflex("1");
        Tabs tabs = new Tabs();
        Tab privateTab = new Tab();
        privateTab.setLabel(Labels.getLabel("admin.menu.private.templates"));
        Tab commonTab = new Tab();
        commonTab.setLabel(Labels.getLabel("admin.menu.common.templates"));
        tabs.appendChild(commonTab);
        tabs.appendChild(privateTab);
        tabs.setParent(textbox);
        Tabpanels tabpanels = new Tabpanels();
        privatePanel = new Tabpanel();
        commonPanel = new Tabpanel();
        tabpanels.appendChild(commonPanel);
        tabpanels.appendChild(privatePanel);
        tabpanels.setParent(textbox);
        textbox.setParent(this);

    }

    public void showDialog(Page page) {
        setClosable(true);
        setMaximizable(true);
        setBorder("normal");

        EnvVo env = Contexts.getEnv();
        String privatePath = WebApps.me().getTemplatePath() + "/" + env.getProjectId() + "/templates";
        Button upload = new Button(Labels.getLabel("admin.template.upload"));
        upload.setStyle("width:100px;margin: 8px 0px 5px 0px;");
        upload.setSclass("ml-4");
        upload.setUpload("true,native,multiple=false");
        upload.setIconSclass("z-icon-upload");
        upload.addEventListener(Events.ON_UPLOAD, this);
        upload.setParent(privatePanel);
        container = new Grid();
        container.setMold("paging");
        container.setPageSize(3);
        container.setWidth("100%");
        container.setVflex("1");
        createContent(container,privatePath);
        container.setParent(privatePanel);



        String commonPath = WebApps.me().getTemplatePath() + "/commonTemplates";
        if (!new File(commonPath).exists()) {
            try {
                FileUtils.forceMkdir(new File(commonPath));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        commonContainer = new Grid();
        commonContainer.setMold("paging");
        commonContainer.setPageSize(3);
        commonContainer.setHflex("1");
        commonContainer.setVflex("1");
        createContent(commonContainer,commonPath);
        commonContainer.setParent(commonPanel);

        setPage(page);
        setSizable(true);
        setPosition("center,top");
        doOverlapped();
    }

    private void createContent(Component parent,String path) {
        File file = new File(FilenameUtils.normalize(path));
        if (!file.exists() || !file.isDirectory()) {
            ((Grid)parent).setEmptyMessage(Labels.getLabel("admin.template.empty"));
        } else {
            File[] files = file.listFiles(f -> f.getName().endsWith(".jar"));
            if (files != null) {
                Rows rows = new Rows();
                Row row = null;
                int pos = 0;
                for (File f : files) {
                    JarFile jarFile = null;
                    ByteArrayOutputStream bos = null;
                    try {
                        jarFile = new JarFile(f);
                        JarEntry entry = jarFile.getJarEntry("META-INF/MANIFEST.MF");
                        if (entry != null) {
                            Properties properties = new Properties();
                            properties.load(jarFile.getInputStream(entry));
                            if (type.equalsIgnoreCase(properties.getProperty("Template-Type"))) {
                                String snapshot = properties.getProperty("Template-Snapshot");
                                String templateFile = properties.getProperty("Template-File");
                                if (Strings.isBlank(snapshot) || jarFile.getJarEntry(snapshot) == null || Strings.isBlank(templateFile) || jarFile.getJarEntry(templateFile) == null)
                                    continue;

                                if(type.contains("Mobile")){
                                    if (pos % 4 == 0) {
                                        row = new Row();
                                        row.setParent(rows);
                                    }
                                }else{
                                    if (pos % 2 == 0) {
                                        row = new Row();
                                        row.setParent(rows);
                                    }
                                }

                                BufferedImage img = ImageIO.read(jarFile.getInputStream(jarFile.getJarEntry(snapshot)));
                                int width = img.getWidth(null);
                                int height = img.getHeight(null);
                                if ((width * 1.0) / IMG_WIDTH < (height * 1.0) / IMG_HEIGHT) {
                                    if (width > IMG_WIDTH)
                                        height = Integer.parseInt(new java.text.DecimalFormat("0").format(height * IMG_WIDTH / (width * 1.0)));
                                } else {
                                    if (height > IMG_HEIGHT)
                                        width = Integer.parseInt(new java.text.DecimalFormat("0").format(width * IMG_HEIGHT / (height * 1.0)));
                                }
                                BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                                Graphics g = bi.getGraphics();
                                g.drawImage(img, 0, 0, width, height, Color.LIGHT_GRAY, null);
                                g.dispose();
                                bos = new ByteArrayOutputStream(4096);
                                ImageIO.write(bi, "jpg", bos);
                                org.zkoss.zul.Div div = new org.zkoss.zul.Div();
                                div.setZclass("w-100 h-100");
                                div.setStyle("text-align:center;margin:10px 0px 10px 0px;");
                                Image image = new Image();
                                image.setStyle("cursor:pointer");
                                image.setContent(new AImage("", bos.toByteArray()));
                                image.setParent(div);
                                div.setParent(row);
                                image.setAttribute("f", f);
                                image.setAttribute("n", templateFile);
                                image.addEventListener(Events.ON_DOUBLE_CLICK, this);
                                pos++;
                            }
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        IOUtils.closeQuietly(jarFile);
                        IOUtils.closeQuietly(bos);
                    }
                }
                rows.setParent(parent);
            }
        }
    }

    @Override
    public void onEvent(Event event) throws Exception {
        EnvVo env = Contexts.getEnv();
        String path = WebApps.me().getTemplatePath() + "/" + env.getProjectId();
        String privatePath = WebApps.me().getTemplatePath() + "/" + env.getProjectId() + "/templates";
        if (event.getName().equals(Events.ON_UPLOAD)) {
            UploadEvent ue = (UploadEvent) event;
            Clients.clearWrongValue(event.getTarget());
            if (ue.getMedia().getName().endsWith(".jar")) {
                FileUtils.writeByteArrayToFile(new File(FilenameUtils.normalize(path + "/templates/" + RandomStringUtils.randomAlphanumeric(10) + ".jar")), ue.getMedia().getByteData());
                if (container.getRows() != null)
                    container.getRows().detach();
                createContent(container,privatePath);
            } else
                Clients.wrongValue(event.getTarget(), Labels.getLabel("explorer.file.reject"));
        } else {
            final File target = new File(FilenameUtils.normalize(path + "/" + name));
            JarFile jarFile = null;
            File backupDir = null;
            String backupContent = cb.getValue();
            try {
                if (target.exists()) {//先备份
                    backupDir = new File(path + "/" + RandomStringUtils.randomAlphanumeric(10));
                    FileUtils.moveDirectory(target, backupDir);
                }
                //解压到目标路径
                FileUtils.forceMkdir(target);
                jarFile = new JarFile((File) event.getTarget().getAttribute("f"));
                Enumeration<JarEntry> enumeration = jarFile.entries();
                while (enumeration.hasMoreElements()) {
                    JarEntry entry = enumeration.nextElement();
                    if (!entry.getName().startsWith("META-INF") && !entry.getName().endsWith(".zul")) {
                        if (entry.isDirectory())
                            FileUtils.forceMkdir(new File(target.getAbsolutePath() + "/" + entry.getName()));
                        else
                            FileUtils.writeByteArrayToFile(new File(target.getAbsolutePath() + "/" + entry.getName()), IOUtils.toByteArray(jarFile.getInputStream(entry)));
                    }
                }
                //zul文件
                JarEntry entry = jarFile.getJarEntry((String) event.getTarget().getAttribute("n"));
                String xul = IOUtils.toString(jarFile.getInputStream(entry), "UTF-8");
                xul = xul.replace("#{708}", name);
                if (logger.isDebugEnabled())
                    logger.debug(xul);
                cb.setValue(xul);
                this.onClose();
            } catch (Exception e) {
                if (logger.isErrorEnabled())
                    logger.error("set template", e);
                //恢复原来的文件和内容
                cb.setValue(backupContent);
                if (backupDir != null) {
                    FileUtils.deleteDirectory(target);
                    FileUtils.moveDirectory(backupDir, target);
                }
                MessageBox.showMessage(Labels.getLabel("message.dialog.title.error"), e.getMessage());
            } finally {
                IOUtils.closeQuietly(jarFile);
                if (backupDir != null)
                    FileUtils.deleteDirectory(backupDir);
            }
        }
    }
}
